package own.stu.bytebuffer.sim.agent;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import net.bytebuddy.implementation.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadLocalRandom;

//@Slf4j
public class SpringmvcInterceptor {

    static ThreadLocalRandom random = ThreadLocalRandom.current();

    /**
     * 被@RuntimeType标准的方法就是拦截方法,此时方法签名[或返回值, 这里不一样，会有转换异常]可以与被拦截方法不一致
     */
    @RuntimeType
    public Object intercept(
            @This Object targetObj,
            @Origin Method targetMethod,
            @AllArguments Object[] targetMethodArgs,
            @SuperCall Callable<?> zCall
    ) throws Exception {
        // log.info("[spring] start targetMethod : {}", targetMethod.getName());
        System.out.println("[spring] start targetMethod : " + targetMethod.getName());
        // long start = System.currentTimeMillis();
        try {

            Object call = zCall.call();

            String className = targetMethod.getDeclaringClass().getName();
            if (Cached.filter(className)) {
                return call;
            }
            String key = (targetObj.getClass().getName() + "." + targetMethod.getName()).trim().intern();
            return Cached.intercept(SpringmvcInterceptor::apply, key, call);
        } catch (Exception e) {
            //log.error("intercept {}", targetMethod.getName(), e);
            throw e;
        } finally {
            // log.info("[spring] end targetMethod : {}, cost : {}", targetMethod.getName(), (System.currentTimeMillis() - start));
        }
    }

    private static Object apply(Object v) {
        try {
            String clazzName = v.getClass().getName();
            /*if(!"jnpf.base.ActionResult".equals(clazzName)){
                return v;
            }*/
            String vJson = JSON.toJSONString(v);
            JSONObject jsonObject = JSON.parseObject(vJson);

            try {
                JSONArray jsonArray = jsonObject.getJSONArray("data");
                if (jsonArray != null && jsonArray.size() > 1) {
                    int delIdx = random.nextInt(jsonArray.size());
                    jsonArray.remove(delIdx);
                    Class<?> aClass = Class.forName(clazzName, false, v.getClass().getClassLoader());
                    return JSON.toJavaObject(jsonObject, aClass);
                }
            } catch (Exception e) {
                JSONObject data = jsonObject.getJSONObject("data");
                JSONArray jsonArray = data.getJSONArray("list");
                if (jsonArray != null && jsonArray.size() > 1) {
                    int delIdx = random.nextInt(jsonArray.size());
                    jsonArray.remove(delIdx);
                    Class<?> aClass = Class.forName(clazzName, false, v.getClass().getClassLoader());
                    return JSON.toJavaObject(jsonObject, aClass);
                }
            }
        } catch (Exception e) {
        }
        return v;
    }
}
